package com.andy.blog.dal.service.impl;

import com.andy.blog.common.constant.UserConstants;
import com.andy.blog.common.core.domain.entity.SysRole;
import com.andy.blog.common.enums.DeleteTypeEnum;
import com.andy.blog.common.exception.BlogServiceException;
import com.andy.blog.common.reponse.BlogResultCode;
import com.andy.blog.common.utils.DateUtils;
import com.andy.blog.common.utils.SecurityUtils;
import com.andy.blog.common.utils.TransformUtils;
import com.andy.blog.dal.domain.SysRoleDO;
import com.andy.blog.dal.domain.SysUserRoleDO;
import com.andy.blog.dal.mapper.SysRoleMapper;
import com.andy.blog.dal.mapper.SysRoleMenuMapper;
import com.andy.blog.dal.mapper.SysUserRoleMapper;
import com.andy.blog.dal.service.SysRoleDalService;
import com.andy.blog.dal.vo.SysRoleVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * Created by andy on 2023-04-05 11:38
 */
@Service
public class SysRoleDalServiceImpl implements SysRoleDalService {
    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysRoleMenuMapper roleMenuMapper;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    /**
     * 根据条件分页查询角色数据
     */
    @Override
    public IPage<SysRoleDO> selectRoleListPage(SysRoleVO sysRoleVO) {
        IPage<SysRoleDO> page = new Page<>(sysRoleVO.getPageNum(), sysRoleVO.getPageSize());
        QueryWrapper<SysRoleDO> queryWrapper = buildQueryWrapper(sysRoleVO);

        return roleMapper.listByPage(page, queryWrapper);
    }

    @NotNull
    private QueryWrapper<SysRoleDO> buildQueryWrapper(SysRoleVO sysRoleVO) {
        QueryWrapper<SysRoleDO> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("r.IS_DELETED", DeleteTypeEnum.DELETE_N.getCode())
                .eq(StringUtils.isNotBlank(sysRoleVO.getStatus()), "r.STATUS", sysRoleVO.getStatus())
                .ge(StringUtils.isNotBlank(sysRoleVO.getBeginTime()), "r.CREATE_TIME", sysRoleVO.getBeginTime())
                .le(StringUtils.isNotBlank(sysRoleVO.getEndTime()), "r.CREATE_TIME", sysRoleVO.getEndTime())
                .lambda()
                .like(StringUtils.isNotBlank(sysRoleVO.getRoleName()), SysRoleDO::getRoleName, sysRoleVO.getRoleName())
                .like(StringUtils.isNotBlank(sysRoleVO.getRoleKey()), SysRoleDO::getRoleKey, sysRoleVO.getRoleKey())
                .orderByAsc(SysRoleDO::getRoleSort);
        return queryWrapper;
    }

    @Override
    public List<SysRoleDO> selectRoleList(SysRoleVO sysRoleVO) {
        QueryWrapper<SysRoleDO> queryWrapper = buildQueryWrapper(sysRoleVO);
        return roleMapper.selectRoleList(queryWrapper);
    }

    /**
     * 根据用户ID查询角色
     *
     * @param userId 用户ID
     * @return 角色列表
     */
    @Override
    public List<SysRoleDO> selectRolesByUserId(Long userId) {
        return roleMapper.selectRolePermissionByUserId(userId);
    }

    /**
     * 根据用户ID查询权限
     *
     * @param userId 用户ID
     * @return 权限列表
     */
    @Override
    public Set<String> selectRolePermissionByUserId(Long userId) {
        List<SysRoleDO> perms = roleMapper.selectRolePermissionByUserId(userId);
        Set<String> permsSet = new HashSet<>();
        for (SysRoleDO perm : perms) {
            if (Objects.nonNull(perm)) {
                permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
            }
        }
        return permsSet;
    }

    /**
     * 查询所有角色
     *
     * @return 角色列表
     */
    @Override
    public List<SysRoleDO> selectRoleAll() {
        return selectRoleList(new SysRoleVO());
    }

    /**
     * 根据用户ID获取角色选择框列表
     *
     * @param userId 用户ID
     * @return 选中角色ID列表
     */
    @Override
    public List<Long> selectRoleListByUserId(Long userId) {
        return roleMapper.selectRoleListByUserId(userId);
    }

    /**
     * 通过角色ID查询角色
     *
     * @param roleId 角色ID
     * @return 角色对象信息
     */
    @Override
    public SysRoleDO selectRoleById(Long roleId) {

        try {
            return roleMapper.selectRoleById(roleId);
        } catch (Exception e) {
            throw new BlogServiceException(BlogResultCode.BLOG_000104, e);
        }
    }

    /**
     * 校验角色名称是否唯一
     */
    @Override
    public boolean checkRoleNameUnique(SysRoleVO sysRoleVO) {
        long roleId = Objects.isNull(sysRoleVO.getId()) ? -1L : sysRoleVO.getId();
        SysRole info = roleMapper.checkRoleNameUnique(sysRoleVO.getRoleName());
        if (Objects.nonNull(info) && info.getId() != roleId) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验角色权限是否唯一
     */
    @Override
    public boolean checkRoleKeyUnique(SysRoleVO sysRoleVO) {
        long roleId = Objects.isNull(sysRoleVO.getId()) ? -1L : sysRoleVO.getId();
        SysRole info = roleMapper.checkRoleKeyUnique(sysRoleVO.getRoleKey());
        if (Objects.nonNull(info) && info.getId() != roleId) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 通过角色ID查询角色使用数量
     *
     * @param roleId 角色ID
     * @return 结果
     */
    @Override
    public int countUserRoleByRoleId(Long roleId) {
        return userRoleMapper.countUserRoleByRoleId(roleId);
    }

    @Override
    public void insertRole(SysRoleVO sysRoleVO) {

        SysRoleDO sysRoleDO = TransformUtils.transform(sysRoleVO, SysRoleDO.class);

        sysRoleDO.setCreateBy(SecurityUtils.getUsername());
        sysRoleDO.setCreateTime(DateUtils.getCurrentDate());
        sysRoleDO.setIsDeleted(DeleteTypeEnum.DELETE_N.getCode());

        try {
            roleMapper.insert(sysRoleDO);
        } catch (Exception e) {
            throw new BlogServiceException(BlogResultCode.BLOG_000100, e);
        }
    }

    /**
     * 修改角色信息
     */
    @Override
    public void updateById(SysRoleVO sysRoleVO) {

        SysRoleDO sysRoleDO = TransformUtils.transform(sysRoleVO, SysRoleDO.class);

        sysRoleDO.setUpdateBy(SecurityUtils.getUsername());
        sysRoleDO.setUpdateTime(DateUtils.getCurrentDate());

        int row;
        try {
            row = roleMapper.updateById(sysRoleDO);
        } catch (Exception e) {
            throw new BlogServiceException(BlogResultCode.BLOG_000101, e);
        }

        if (row <= 0) {
            throw new BlogServiceException(BlogResultCode.BLOG_000101);
        }
    }

    /**
     * 通过角色ID删除角色
     *
     * @param roleId 角色ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteRoleById(Long roleId) {
        // 删除角色与菜单关联
        roleMenuMapper.deleteRoleMenuByRoleId(roleId);
        return roleMapper.deleteRoleById(roleId);
    }

    /**
     * 批量选择授权用户角色
     *
     * @param roleId  角色ID
     * @param userIds 需要授权的用户数据ID
     * @return 结果
     */
    @Override
    public int insertAuthUsers(Long roleId, Long[] userIds) {
        // 新增用户与角色管理
        List<SysUserRoleDO> list = new ArrayList<>();
        for (Long userId : userIds) {
            SysUserRoleDO ur = new SysUserRoleDO();
            ur.setUserId(userId);
            ur.setRoleId(roleId);
            list.add(ur);
        }
        return userRoleMapper.batchUserRole(list);
    }
}
